home *** CD-ROM | disk | FTP | other *** search
/ Multimedia Jumpstart / Multimedia Microsoft Jumpstart Version 1.1a (Microsoft).BIN / develpmt / sdk / vfw11.win / vfwdk / captest.c_ / captest.bin
Encoding:
Text File  |  1993-11-19  |  32.5 KB  |  898 lines

  1. /****************************************************************************
  2.  *
  3.  *   captest.c: Source Code for the CapTest Sample Program
  4.  * 
  5.  *   Microsoft Video for Windows Capture Class Sample Program
  6.  *
  7.  ***************************************************************************/
  8. /**************************************************************************
  9.  *
  10.  *  THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
  11.  *  KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  12.  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
  13.  *  PURPOSE.
  14.  *
  15.  *  Copyright (c) 1992, 1993  Microsoft Corporation.  All Rights Reserved.
  16.  * 
  17.  **************************************************************************/
  18.  
  19.  
  20. // Enable or disable program functionality with the following flags!
  21.  
  22. #define ENABLE_ERROR_CALLBACK           1
  23. #define ENABLE_STATUS_CALLBACK          1
  24. #define ENABLE_VIDEOFRAME_CALLBACKS     0
  25. #define ENABLE_VIDEOSTREAM_CALLBACKS    0
  26. #define ONLY_CAPTURE_TO_CALLBACKS       0
  27.  
  28. #include <windows.h>
  29. #include <windowsx.h>
  30. #include <commdlg.h>
  31. #include <mmsystem.h>
  32. #include <msvideo.h>
  33. #include <mmreg.h>
  34. #include <io.h>
  35. #include <fcntl.h>
  36. #include <stdio.h>
  37. #include <stdlib.h>
  38. #include <memory.h>
  39. #include <dos.h>
  40.  
  41. #include <avicap.h>
  42. #include <msacm.h>
  43. #include "captest.h"
  44.  
  45. //
  46. // Global Variables
  47. //
  48. char           gachAppName[]  = "CapTestApp" ;
  49. char           gachIconName[] = "CapTestIcon" ;
  50. char           gachMenuName[] = "CapTestMenu" ;
  51. char           gachMCIDeviceName[21] = "VideoDisc" ;  // default MCI device
  52. char           gachString[128] ;
  53. char           gachBuffer[200] ;
  54.  
  55. HINSTANCE      ghInst ;
  56. HWND           ghWndMain ;
  57. HWND           ghWndCap ;
  58. HANDLE         ghAccel ;
  59. WORD           gwDeviceIndex ;
  60. WORD           gwPalFrames = DEF_PALNUMFRAMES ; 
  61. WORD           gwPalColors = DEF_PALNUMCOLORS ;
  62. WORD           gwCapFileSize ;
  63. DWORD          gdwFrameNum ;
  64. DWORD          gdwVideoNum ;
  65. BOOL           fHaveDialogUp = FALSE;
  66.  
  67. CAPSTATUS      gCapStatus ;
  68. CAPDRIVERCAPS  gCapDriverCaps ;
  69. CAPTUREPARMS   gCapParms ;
  70.  
  71. LPWAVEFORMATEX glpwfex ;
  72.  
  73. FARPROC        fpErrorCallback ;
  74. FARPROC        fpStatusCallback ;
  75. FARPROC        fpFrameCallback ;
  76. FARPROC        fpVideoCallback ;
  77.  
  78. //
  79. // Function prototypes
  80. //
  81. LONG FAR PASCAL MainWndProc(HWND, UINT, UINT, LONG) ;
  82. LRESULT FAR PASCAL ErrorCallbackProc(HWND, int, LPSTR) ;
  83. LRESULT FAR PASCAL StatusCallbackProc(HWND, int, LPSTR) ;
  84. LRESULT FAR PASCAL FrameCallbackProc(HWND, LPVIDEOHDR) ;
  85. LRESULT FAR PASCAL VideoCallbackProc(HWND, LPVIDEOHDR) ;
  86.  
  87. //
  88. // WinMain: Application Entry Point Function
  89. //
  90. int PASCAL WinMain(HANDLE hInstance, HANDLE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow)
  91. {
  92. ///////////////////////////////////////////////////////////////////////
  93. //  hInstance:      handle for this instance
  94. //  hPrevInstance:  handle for possible previous instances
  95. //  lpszCmdLine:    long pointer to exec command line
  96. //  nCmdShow:       Show code for main window display
  97. ///////////////////////////////////////////////////////////////////////
  98.  
  99.     MSG          msg ;
  100.     WNDCLASS     wc ;
  101.  
  102.     ghInst = hInstance ;
  103.     if (! hPrevInstance) {
  104.         // If it's the first instance, register the window class
  105.         wc.lpszClassName = gachAppName ;
  106.         wc.hInstance     = hInstance ;
  107.         wc.lpfnWndProc   = MainWndProc ;
  108.         wc.hCursor       = LoadCursor(NULL, IDC_ARROW) ;
  109.         wc.hIcon         = LoadIcon(hInstance, gachIconName) ;
  110.         wc.lpszMenuName  = gachMenuName ;
  111.         wc.hbrBackground = GetStockObject(WHITE_BRUSH) ;
  112.         wc.style         = CS_HREDRAW | CS_VREDRAW ;
  113.         wc.cbClsExtra    = 0 ;
  114.         wc.cbWndExtra    = 0 ;
  115.  
  116.         if (! RegisterClass(&wc)) {
  117.             LoadString(ghInst, IDS_ERR_REGISTER_CLASS, gachString, sizeof(gachString)) ;
  118.             MessageBox(NULL, gachString, NULL,
  119. #ifdef BIDI
  120.                 MB_RTL_READING |
  121. #endif
  122.  
  123.             MB_ICONEXCLAMATION) ;
  124.             return NULL ;    
  125.         }
  126.     }
  127.  
  128.     // Create Application's Main window
  129.     ghWndMain =
  130. #ifdef BIDI
  131.         CreateWindowEx(WS_EX_BIDI_SCROLL |  WS_EX_BIDI_MENU |WS_EX_BIDI_NOICON,
  132. #else
  133.         CreateWindow (
  134. #endif
  135.                              gachAppName,
  136.                              "Capture Test App", 
  137.                              WS_CAPTION      |   
  138.                              WS_SYSMENU      |   
  139.                              WS_MINIMIZEBOX  |   
  140.                              WS_MAXIMIZEBOX  |   
  141.                              WS_THICKFRAME   |   
  142.                              WS_CLIPCHILDREN |   
  143.                              WS_OVERLAPPED,
  144.                              CW_USEDEFAULT, 0,   
  145.                              320, 240,   
  146.                              NULL,               
  147.                              NULL,               
  148.                              ghInst,             
  149.                              NULL) ;
  150.     if (ghWndMain == NULL) {
  151.         LoadString(ghInst, IDS_ERR_CREATE_WINDOW, gachString, sizeof(gachString)) ;
  152.         MessageBox(NULL, gachString, NULL,
  153. #ifdef BIDI
  154.                 MB_RTL_READING |
  155. #endif
  156.  
  157.         MB_ICONEXCLAMATION | MB_OK) ;
  158.         return IDS_ERR_CREATE_WINDOW ;
  159.     }
  160.  
  161.     ShowWindow(ghWndMain, nCmdShow) ;
  162.     UpdateWindow(ghWndMain) ;
  163.     ghAccel = LoadAccelerators(ghInst, gachAppName) ;
  164.  
  165.     // All set; get and process messages
  166.     while (GetMessage(&msg, NULL, 0, 0)) {
  167.         if (! TranslateAccelerator(ghWndMain, ghAccel, &msg)) {
  168.             TranslateMessage(&msg) ;
  169.             DispatchMessage(&msg) ;
  170.         }
  171.     }
  172.  
  173.     return msg.wParam ;
  174. }  // End of WinMain
  175.  
  176.  
  177. //
  178. // ErrorCallbackProc: Error Callback Function
  179. //
  180. LRESULT FAR PASCAL ErrorCallbackProc(HWND hWnd, int nErrID, LPSTR lpErrorText)
  181. {
  182. ////////////////////////////////////////////////////////////////////////
  183. //  hWnd:          Application main window handle
  184. //  nErrID:        Error code for the encountered error
  185. //  lpErrorText:   Error text string for the encountered error 
  186. ////////////////////////////////////////////////////////////////////////
  187.  
  188.     if (!ghWndMain)
  189.         return FALSE;
  190.  
  191.     if (nErrID == 0)            // Starting a new major function
  192.         return TRUE;            // Clear out old errors...
  193.  
  194.     // Show the error ID and text 
  195.     wsprintf(gachBuffer, "Error# %d", nErrID) ;
  196.  
  197.     MessageBox(hWnd, lpErrorText, gachBuffer,
  198. #ifdef BIDI
  199.                 MB_RTL_READING |
  200. #endif
  201.                 MB_OK | MB_ICONEXCLAMATION) ;
  202.  
  203.     return (LRESULT) TRUE ;
  204. }
  205.  
  206.  
  207. //
  208. // StatusCallbackProc: Status Callback Function
  209. //
  210. LRESULT FAR PASCAL StatusCallbackProc(HWND hWnd, int nID, LPSTR lpStatusText)
  211. {
  212. ////////////////////////////////////////////////////////////////////////
  213. //  hWnd:           Application main window handle
  214. //  nID:            Status code for the current status
  215. //  lpStatusText:   Status text string for the current status 
  216. ////////////////////////////////////////////////////////////////////////
  217.  
  218.     if (!ghWndMain)
  219.         return FALSE;
  220.  
  221.     if (nID == 0) {              // Zero means clear old status messages
  222.         SetWindowText(ghWndMain, (LPSTR) gachAppName) ;
  223.         return (LRESULT) TRUE ;
  224.     }
  225.  
  226.     // Show the status ID and status text...
  227.     // unless we get the "end of capture" message
  228.     if (nID != IDS_CAP_END) {
  229.         wsprintf(gachBuffer, "Status# %d: %s", nID, lpStatusText) ;
  230.         SetWindowText(ghWndMain, (LPSTR)gachBuffer) ;
  231.         UpdateWindow (ghWndMain);
  232.     }
  233.         
  234.     return (LRESULT) TRUE ;
  235. }
  236.  
  237.  
  238. //
  239. // FrameCallbackProc: Frame Callback Function
  240. // Called whenever a new frame is captured but not streaming
  241. //
  242. LRESULT FAR PASCAL FrameCallbackProc(HWND hWnd, LPVIDEOHDR lpVHdr)
  243. {
  244. ////////////////////////////////////////////////////////////////////////
  245. //  hWnd:       Application main window handle
  246. //  lpVHdr:     long pointer to VideoHdr struct containing captured 
  247. //              frame information
  248. ////////////////////////////////////////////////////////////////////////
  249.  
  250.     if (!ghWndMain)
  251.         return FALSE;
  252.  
  253.     wsprintf(gachBuffer, "Preview frame# %ld ", gdwFrameNum++) ;  
  254.  
  255.     SetWindowText(ghWndMain, (LPSTR)gachBuffer) ;
  256.     UpdateWindow (ghWndMain);
  257.  
  258.     return (LRESULT) TRUE ;
  259. }
  260.  
  261.  
  262. //
  263. // VideoCallbackProc: Video Stream Callback Function
  264. // Called whenever a new frame is captured while streaming
  265. //
  266. LRESULT FAR PASCAL VideoCallbackProc(HWND hWnd, LPVIDEOHDR lpVHdr)
  267. {
  268. ////////////////////////////////////////////////////////////////////////
  269. //  hWnd:       Application main window handle
  270. //  lpVHdr:     long pointer to VideoHdr struct containing captured 
  271. //              frame information
  272. ////////////////////////////////////////////////////////////////////////
  273.  
  274.     wsprintf(gachBuffer, "Streaming frame# %ld ", gdwVideoNum++) ;  
  275.  
  276.     SetWindowText(ghWndMain, (LPSTR)gachBuffer) ;
  277.     UpdateWindow (ghWndMain);
  278.  
  279.     return (LRESULT) TRUE ;
  280. }
  281.  
  282.  
  283. //
  284. // CenterCaptureWindow: Placess Capture Window at the Center of Main Window
  285. //
  286. static void CenterCaptureWindow(HWND hWndM, HWND hWndC)
  287. {
  288. ////////////////////////////////////////////////////////////////////////
  289. //  hWndM:      Application main window handle
  290. //  hWndC:      Capture window handle
  291. ////////////////////////////////////////////////////////////////////////
  292.  
  293.     RECT       MainRect ;
  294.     RECT       CapRect ;
  295.     WORD       wCapXPos ;
  296.     WORD       wCapYPos ;
  297.  
  298.     // Get the sizes of main and capture windows and 
  299.     // calculate the location for centering
  300.     GetClientRect(hWndM, &MainRect) ;
  301.     GetClientRect(hWndC, &CapRect) ;
  302.     wCapXPos = max(0, (Width(MainRect) - Width(CapRect)) / 2) ;
  303.     wCapYPos = max(0, (Height(MainRect) - Height(CapRect)) / 2) ;
  304.  
  305.     // Position the capture window at the required location
  306.     MoveWindow(hWndC, wCapXPos, wCapYPos, Width(CapRect),
  307.                Height(CapRect), TRUE) ;
  308. }
  309.  
  310.  
  311. //
  312. // StartNewVideoChannel: Gets Selected Driver's Caps -- Updates menu, 
  313. //                       Checks Image Size -- Resizes display window,
  314. //                       Enables Preview (at 15 FPS rate)
  315. //
  316. static void StartNewVideoChannel(HWND hWndM, HWND hWndC, WORD wIndex)
  317. {
  318. ////////////////////////////////////////////////////////////////////////
  319. //  hWndM:      Application main window handle
  320. //  hWndC:      Capture window handle
  321. //  wIndex:     Selected capture driver index
  322. ////////////////////////////////////////////////////////////////////////
  323.  
  324.     HMENU       hMenu = GetMenu(hWndM) ;
  325.  
  326.     // Get capture driver settings and update menu
  327.     capDriverGetCaps(hWndC, &gCapDriverCaps, sizeof(CAPDRIVERCAPS)) ;
  328.     EnableMenuItem(hMenu, IDM_O_OVERLAY, MF_BYCOMMAND |
  329.                 gCapDriverCaps.fHasOverlay ? MF_ENABLED : MF_GRAYED) ;
  330.     EnableMenuItem(hMenu, IDM_O_VIDEOFORMAT, MF_BYCOMMAND |
  331.                 gCapDriverCaps.fHasDlgVideoFormat ? MF_ENABLED : MF_GRAYED) ;
  332.     EnableMenuItem(hMenu, IDM_O_VIDEOSOURCE, MF_BYCOMMAND |
  333.                 gCapDriverCaps.fHasDlgVideoSource ? MF_ENABLED : MF_GRAYED) ;
  334.     EnableMenuItem(hMenu, IDM_O_VIDEODISPLAY, MF_BYCOMMAND |
  335.                 gCapDriverCaps.fHasDlgVideoDisplay ? MF_ENABLED : MF_GRAYED) ;
  336.  
  337.     // Get video format and adjust capture window
  338.     capGetStatus(hWndC, &gCapStatus, sizeof(CAPSTATUS)) ;
  339.     SetWindowPos(hWndC, NULL, 0, 0, gCapStatus.uiImageWidth,
  340.                  gCapStatus.uiImageHeight, SWP_NOZORDER | SWP_NOMOVE) ;
  341.  
  342.     // Start preview by default
  343.     capPreviewRate(hWndC, MS_FOR_15FPS) ;
  344.     capPreview(hWndC, TRUE) ;
  345.  
  346.     // Put check mark beside appropriate menu options
  347.     CheckMenuItem(hMenu, wIndex + IDM_O_DRIVERS, MF_BYCOMMAND | MF_CHECKED) ;
  348. }
  349.  
  350.  
  351. //
  352. // MenuProc: Processes All Menu-based Operations
  353. //
  354. long FAR PASCAL MenuProc(HWND hWnd, WORD wParam, LONG lParam)
  355. {
  356. ////////////////////////////////////////////////////////////////////////
  357. //  hWnd:      Application main window handle
  358. //  hMenu:     Application menu handle
  359. //  wParam:    Menu option 
  360. //  lParam:    Additional info for any menu option
  361. ////////////////////////////////////////////////////////////////////////
  362.  
  363.     FARPROC      fpAboutProc ;
  364.     FARPROC      fpCapSetUpProc ;
  365.     FARPROC      fpMakePaletteProc ;
  366.     FARPROC      fpAllocCapFileProc ;
  367.     OPENFILENAME ofn ;
  368.     WORD         wError ; 
  369.     WORD         wIndex ;
  370.     BOOL         fResult ;
  371.     DWORD        dwSize ;
  372.     char         achBuffer[_MAX_PATH] ;
  373.     char         achFileName[_MAX_PATH] ;
  374.     char         *szFileFilter = "Microsoft AVI\0"
  375.                                  "*.avi\0"
  376.                                  "All Files\0"
  377.                                  "*.*\0" ;
  378.  
  379.     HMENU hMenu = GetMenu(hWnd) ;
  380.  
  381.     capGetStatus(ghWndCap, &gCapStatus, sizeof(CAPSTATUS)) ;
  382.  
  383.     // If yielding during capture, don't allow other messages
  384.     if (gCapStatus.fCapturingNow) {
  385.         MessageBeep ((UINT) -1);
  386.         return FALSE;
  387.     }
  388.  
  389.     switch (wParam) {
  390.         case IDM_F_SETCAPTUREFILE:
  391.         {
  392.             LPSTR p;
  393.  
  394.             // Get current capture file name and 
  395.             // then try to get the new capture file name
  396.             if (wError = capFileGetCaptureFile(ghWndCap, achFileName, 
  397.                                         sizeof(achFileName))) {
  398.  
  399.                 // Get just the path info
  400.                 // Terminate the full path at the last backslash
  401.                 lstrcpy (achBuffer, achFileName);
  402.                 for (p = achBuffer + lstrlen(achBuffer); p > achBuffer; p--) {
  403.                     if (*p == '\\') {
  404.                         *(p+1) = '\0';
  405.                         break;
  406.                     }
  407.                 }
  408.  
  409.                 _fmemset(&ofn, 0, sizeof(OPENFILENAME)) ;
  410.                 ofn.lStructSize = sizeof(OPENFILENAME) ;
  411.                 ofn.hwndOwner = hWnd ;
  412.                 ofn.lpstrFilter = szFileFilter ;
  413.                 ofn.nFilterIndex = 0 ;
  414.                 ofn.lpstrFile = achFileName ;
  415.                 ofn.nMaxFile = sizeof(achFileName) ;
  416.                 ofn.lpstrFileTitle = NULL;
  417.                 ofn.lpstrTitle = "Set Capture File" ;
  418.                 ofn.nMaxFileTitle = 0 ;
  419.                 ofn.lpstrInitialDir = achBuffer;
  420.                 ofn.Flags =
  421. #ifdef BIDI
  422.                 OFN_BIDIDIALOG |
  423. #endif
  424.                 OFN_HIDEREADONLY |
  425.                 OFN_NOREADONLYRETURN |
  426.                 OFN_PATHMUSTEXIST ;
  427.                 
  428.                 fHaveDialogUp = TRUE;
  429.                 if (GetOpenFileName(&ofn))
  430.                     // If the user has hit OK then set capture file name
  431.                     capFileSetCaptureFile(ghWndCap, achFileName) ;
  432.                 fHaveDialogUp = FALSE;
  433.             }
  434.         }
  435.         break; 
  436.  
  437.         case IDM_F_SAVEVIDEOAS:
  438.             // Get the current capture file name and
  439.             // then get the substitute file name to save video in
  440.             if (wError = capFileGetCaptureFile(ghWndCap, achFileName, sizeof(achFileName))) {
  441.  
  442.                 _fmemset(&ofn, 0, sizeof(OPENFILENAME)) ;
  443.                 ofn.lStructSize = sizeof(OPENFILENAME) ;
  444.                 ofn.hwndOwner = hWnd ;
  445.                 ofn.lpstrFilter = szFileFilter ;
  446.                 ofn.nFilterIndex = 0 ;
  447.                 ofn.lpstrFile = achFileName ;
  448.                 ofn.nMaxFile = sizeof(achFileName) ;
  449.                 ofn.lpstrFileTitle = NULL ;
  450.                 ofn.lpstrTitle = "Save Video As..." ;
  451.                 ofn.nMaxFileTitle = 0 ;
  452.                 ofn.lpstrInitialDir = NULL ;
  453.                 ofn.Flags =
  454. #ifdef BIDI
  455.                 OFN_BIDIDIALOG |
  456. #endif
  457.                 OFN_PATHMUSTEXIST ;
  458.  
  459.                 fHaveDialogUp = TRUE;
  460.                 if (GetSaveFileName(&ofn))
  461.                     // If the user has hit OK then set save file name
  462.                     capFileSaveAs(ghWndCap, achFileName) ;
  463.                 fHaveDialogUp = FALSE;
  464.             }
  465.             break; 
  466.  
  467.         case IDM_F_ALLOCATESPACE:
  468.             fpAllocCapFileProc = MakeProcInstance(AllocCapFileProc, ghInst) ;
  469.             fHaveDialogUp = TRUE;
  470.             if (DialogBox(ghInst, MAKEINTRESOURCE(IDD_AllocCapFileSpace), 
  471.                           hWnd, fpAllocCapFileProc)) 
  472.                 // If user has hit OK then alloc requested capture file space
  473.                 if (! capFileAlloc(ghWndCap, (long) gwCapFileSize * ONEMEG))
  474.                     MessageBox(NULL, "Can't pre-allocate capture file space", 
  475.                                "Error",
  476. #ifdef BIDI
  477.                                 MB_RTL_READING |
  478. #endif
  479.                                 MB_OK | MB_ICONEXCLAMATION) ;
  480.             FreeProcInstance(fpAllocCapFileProc) ;
  481.             fHaveDialogUp = FALSE;
  482.             break ;
  483.  
  484.         case IDM_F_EXIT:
  485.             DestroyWindow(hWnd) ;
  486.             break; 
  487.  
  488.         case IDM_E_COPY:
  489.             capEditCopy(ghWndCap) ;
  490.             break; 
  491.  
  492.         case IDM_E_PASTEPALETTE:
  493.             capPalettePaste(ghWndCap) ;
  494.             break; 
  495.  
  496.         case IDM_O_PREVIEW:
  497.             // Toggle Preview
  498.             capGetStatus(ghWndCap, &gCapStatus, sizeof(CAPSTATUS)) ;
  499.             capPreview(ghWndCap, !gCapStatus.fLiveWindow) ;
  500.             break; 
  501.  
  502.         case IDM_O_OVERLAY:
  503.             // Toggle Overlay
  504.             capGetStatus(ghWndCap, &gCapStatus, sizeof(CAPSTATUS)) ;
  505.             capOverlay(ghWndCap, !gCapStatus.fOverlayWindow) ;
  506.             break ;
  507.  
  508.         case IDM_O_AUDIOFORMAT:
  509. #define USE_ACM
  510. #ifdef  USE_ACM
  511.             {
  512.                 ACMFORMATCHOOSE cfmt;
  513.  
  514.                 // Ask the ACM what the largest wave format is.....
  515.                 acmMetrics(NULL,
  516.                             ACM_METRIC_MAX_SIZE_FORMAT,
  517.                             &dwSize);
  518.  
  519.                 // Get the current audio format
  520.                 dwSize = max (dwSize, capGetAudioFormatSize (ghWndCap));
  521.                 glpwfex = (LPWAVEFORMATEX) GlobalAllocPtr(GHND, dwSize) ;
  522.                 capGetAudioFormat(ghWndCap, glpwfex, (WORD)dwSize) ;
  523.  
  524.                 _fmemset (&cfmt, 0, sizeof (ACMFORMATCHOOSE));
  525.                 cfmt.cbStruct = sizeof (ACMFORMATCHOOSE);
  526.                 cfmt.fdwStyle =  ACMFORMATCHOOSE_STYLEF_INITTOWFXSTRUCT;
  527.                 cfmt.fdwEnum =   ACM_FORMATENUMF_HARDWARE |
  528.                                  ACM_FORMATENUMF_INPUT;
  529.                 cfmt.hwndOwner = hWnd;
  530.                 cfmt.pwfx =     glpwfex;
  531.                 cfmt.cbwfx =    dwSize;
  532.                 fHaveDialogUp = TRUE;
  533.                 if (!acmFormatChoose(&cfmt))
  534.                     capSetAudioFormat(ghWndCap, glpwfex, (WORD)dwSize) ;
  535.                 fHaveDialogUp = FALSE;
  536.  
  537.                 GlobalFreePtr(glpwfex) ;
  538.             }
  539. #else
  540.             // If not using ACM, remove the reference in the link line
  541.             // of makefile.
  542.             {
  543.                 FARPROC      fpAudioFormatProc ;
  544.  
  545.                 // Get current audio format and then find required format
  546.                 dwSize = capGetAudioFormatSize (ghWndCap);
  547.                 glpwfex = (LPWAVEFORMATEX) GlobalAllocPtr(GHND, dwSize) ;
  548.                 capGetAudioFormat(ghWndCap, glpwfex, (WORD)dwSize) ;
  549.  
  550.                 fpAudioFormatProc = MakeProcInstance(AudioFormatProc, ghInst) ;
  551.                 fHaveDialogUp = TRUE;
  552.                 if (DialogBox(ghInst, MAKEINTRESOURCE(IDD_AudioFormat), hWnd, 
  553.                         fpAudioFormatProc))
  554.                         // If the user has hit OK, set the new audio format
  555.                         capSetAudioFormat(ghWndCap, glpwfex, (WORD)dwSize) ;
  556.                 FreeProcInstance(fpAudioFormatProc) ;
  557.                 fHaveDialogUp = FALSE;
  558.                 GlobalFreePtr(glpwfex) ;
  559.             }
  560. #endif
  561.             break ;
  562.  
  563.         case IDM_O_VIDEOFORMAT:
  564.             if (gCapDriverCaps.fHasDlgVideoFormat) {
  565.                 // Only if the driver has a "Video Format" dialog box
  566.                 fHaveDialogUp = TRUE;
  567.                 if (capDlgVideoFormat(ghWndCap)) {  // If successful,
  568.                     // Get the new image dimension and center capture window
  569.                     capGetStatus(ghWndCap, &gCapStatus, sizeof(CAPSTATUS)) ;
  570.                     SetWindowPos(ghWndCap, NULL, 0, 0, gCapStatus.uiImageWidth,
  571.                         gCapStatus.uiImageHeight, SWP_NOZORDER | SWP_NOMOVE) ;
  572.                     CenterCaptureWindow(hWnd, ghWndCap) ;
  573.                 }
  574.                 fHaveDialogUp = FALSE;
  575.             }
  576.             break; 
  577.  
  578.         case IDM_O_VIDEOSOURCE:
  579.             if (gCapDriverCaps.fHasDlgVideoSource) {
  580.                 // Only if the driver has a "Video Source" dialog box
  581.                 fHaveDialogUp = TRUE;
  582.                 capDlgVideoSource(ghWndCap) ;
  583.                 fHaveDialogUp = FALSE;
  584.             }
  585.             break ;
  586.  
  587.         case IDM_O_VIDEODISPLAY:
  588.             fHaveDialogUp = TRUE;
  589.             if (gCapDriverCaps.fHasDlgVideoDisplay) {
  590.                 // Only if the driver has a "Video Display" dialog box
  591.                 capDlgVideoDisplay(ghWndCap) ;
  592.             }
  593.             fHaveDialogUp = FALSE;
  594.             break ;
  595.  
  596.         case IDM_O_PALETTE:
  597.             fpMakePaletteProc = MakeProcInstance(MakePaletteProc, ghInst) ;
  598.             fHaveDialogUp = TRUE;
  599.             if (DialogBox(ghInst, MAKEINTRESOURCE(IDD_MakePalette), hWnd, 
  600.                           fpMakePaletteProc))
  601.                 // If the user has hit OK, capture palette with the
  602.                 // specified number of colors and frames
  603.                 capPaletteAuto(ghWndCap, gwPalFrames, gwPalColors) ;
  604.             fHaveDialogUp = FALSE;
  605.             FreeProcInstance(fpMakePaletteProc) ;
  606.             break; 
  607.  
  608.         case IDM_C_CAPTUREVIDEO:
  609.             // Capture video sequence
  610.             gdwFrameNum = 0 ;  // Reset single frame counter
  611.             gdwVideoNum = 0 ;  // Reset video stream counter
  612.  
  613. #if ONLY_CAPTURE_TO_CALLBACKS
  614.             // Here be dragons!
  615.             // Watch for re-entrancy if you enable yielding during capture
  616.             // Only send streams to callbacks, not to a file
  617.             capCaptureGetSetup(ghWndCap, &gCapParms, sizeof(CAPTUREPARMS)) ;
  618.             gCapParms.fYield = TRUE;    // Watch out!
  619.             capCaptureSetSetup(ghWndCap, &gCapParms, sizeof(CAPTUREPARMS)) ;
  620.             fResult = capCaptureSequenceNoFile(ghWndCap) ;
  621. #else
  622.             fResult = capCaptureSequence(ghWndCap) ;
  623. #endif
  624.             break; 
  625.  
  626.         case IDM_C_CAPTUREFRAME:
  627.             gdwFrameNum = 0 ;  // Start counting single frames
  628.             // Turn off overlay / preview (gets turned off by frame capture)
  629.         capPreview(ghWndCap, FALSE);
  630.         capOverlay(ghWndCap, FALSE);
  631.  
  632.             // Grab a frame
  633.             fResult = capGrabFrameNoStop(ghWndCap) ;
  634.             break; 
  635.  
  636.         case IDM_C_CAPTURESETTINGS:
  637.             // Get the current setup for video capture
  638.             capCaptureGetSetup(ghWndCap, &gCapParms, sizeof(CAPTUREPARMS)) ;
  639.  
  640.             // Invoke a Dlg box to setup all the params
  641.             fpCapSetUpProc = MakeProcInstance(CapSetUpProc, ghInst) ;
  642.             fHaveDialogUp = TRUE;
  643.             if (DialogBox(ghInst, MAKEINTRESOURCE(IDD_CapSetUp), hWnd, fpCapSetUpProc)) {
  644.                 // If the user has hit OK, set the new setup info
  645.  
  646. #if ONLY_CAPTURE_TO_CALLBACKS
  647.                 // Here be dragons!
  648.                 // Watch for re-entrancy if you enable yielding during capture
  649.                 gCapParms.fYield = TRUE;
  650. #endif
  651.  
  652.                 capCaptureSetSetup(ghWndCap, &gCapParms, sizeof(CAPTUREPARMS)) ;
  653.             }
  654.             fHaveDialogUp = FALSE;
  655.             FreeProcInstance(fpCapSetUpProc) ;
  656.             break; 
  657.  
  658.         case IDM_O_CHOOSECOMPRESSOR:
  659.             fHaveDialogUp = TRUE;
  660.             capDlgVideoCompression(ghWndCap);
  661.             fHaveDialogUp = FALSE;
  662.             break; 
  663.  
  664.         case IDM_H_ABOUT:
  665.             fpAboutProc = MakeProcInstance(AboutProc, ghInst) ;
  666.             fHaveDialogUp = TRUE;
  667.             DialogBox(ghInst, MAKEINTRESOURCE(IDD_HelpAboutBox), hWnd, fpAboutProc) ;
  668.             fHaveDialogUp = FALSE;
  669.             FreeProcInstance(fpAboutProc) ;
  670.             break ;
  671.  
  672.         default:
  673.             // There is a chance, a driver change has been requested
  674.             if ( IsDriverIndex(wParam) ) { 
  675.                 // If it's a valid driver index...
  676.                 if (wParam - IDM_O_DRIVERS != gwDeviceIndex) { 
  677.                     // and a different one too then we need to do the rest
  678.  
  679.                     // Turn off preview/overlay, uncheck current driver option
  680.                     capPreview(ghWndCap, FALSE) ;
  681.                     capOverlay(ghWndCap, FALSE) ;
  682.                     CheckMenuItem(GetMenu(hWnd), gwDeviceIndex + IDM_O_DRIVERS, 
  683.                                   MF_BYCOMMAND | MF_UNCHECKED) ;
  684.  
  685.                     // Connect to requested driver
  686.                     if ( capDriverConnect(ghWndCap, (wIndex = wParam - IDM_O_DRIVERS)) ) {
  687.                         // Connect worked fine -- update menu, start new driver...
  688.                         CheckMenuItem(GetMenu(hWnd), wParam, MF_BYCOMMAND | MF_CHECKED) ;
  689.                         gwDeviceIndex = wParam - IDM_O_DRIVERS ;
  690.                         StartNewVideoChannel(hWnd, ghWndCap, gwDeviceIndex) ;
  691.                         CenterCaptureWindow(hWnd, ghWndCap) ;
  692.                     }
  693.                     else {
  694.                         // if connect failed, re-connect back to previous driver
  695.                         if (! capDriverConnect(ghWndCap, gwDeviceIndex)) {
  696.                             MessageBox(hWnd, "Now can't connect back to previous driver !!",
  697.                                        "Error",
  698. #ifdef BIDI
  699.                             MB_RTL_READING |
  700. #endif
  701.  
  702.                             MB_OK | MB_ICONSTOP) ;
  703.                             return -1L ;
  704.                         }
  705.                         else
  706.                             // Re-start previous driver as it was before
  707.                             StartNewVideoChannel(hWnd, ghWndCap, gwDeviceIndex) ;
  708.                             CenterCaptureWindow(hWnd, ghWndCap) ;
  709.                     }
  710.                 }   // end of if ( != gwDeviceIndex)
  711.             }   // end of if (IsDriverIndex())
  712.             else {
  713.                 wsprintf(achBuffer, "How could you specify this (%u) Driver Index ?",
  714.                          wParam - IDM_O_DRIVERS) ;
  715.                 MessageBox(hWnd, achBuffer, "Oops!!",
  716. #ifdef BIDI
  717.                 MB_RTL_READING |
  718. #endif
  719.                 MB_OK | MB_ICONEXCLAMATION) ;
  720.             }
  721.  
  722.             break ;
  723.     }
  724.  
  725.     return 0L ;
  726. }
  727.  
  728.  
  729. //
  730. // MainWndProc: Application Main Window Procedure
  731. //
  732. LONG FAR PASCAL MainWndProc(HWND hWnd, UINT Message, UINT wParam, LONG lParam)
  733. {
  734. ////////////////////////////////////////////////////////////////////////
  735. //  hWnd:      Application main window handle
  736. //  Message:   Next message to be processed
  737. //  wParam:    WORD param for the message 
  738. //  lParam:    LONG param for the message
  739. ////////////////////////////////////////////////////////////////////////
  740.  
  741.     switch (Message) {
  742.         case WM_COMMAND:
  743.             MenuProc(hWnd, wParam, lParam) ;
  744.             break ;
  745.  
  746.         case WM_CREATE:
  747.         {
  748.             char    achDeviceName[80] ;
  749.             char    achDeviceVersion[100] ;
  750.             char    achBuffer[100] ;
  751.             WORD    wDriverCount = 0 ;
  752.             WORD    wIndex ;
  753.             WORD    wError ;
  754.             HMENU   hMenu ;
  755.  
  756.             // First create the capture window 
  757.             ghWndCap = capCreateCaptureWindow((LPSTR)"Capture Window",
  758.                                               WS_CHILD | WS_VISIBLE,
  759.                                               0, 0, 160, 120,
  760.                                               (HWND) hWnd, (int) 0) ;
  761.  
  762.             hMenu = GetSubMenu(GetMenu(hWnd), 2) ;  // 2 for "Option"
  763.  
  764. #if ENABLE_ERROR_CALLBACK
  765.             // Register the status and error callbacks before driver connect
  766.             fpErrorCallback = MakeProcInstance((FARPROC)ErrorCallbackProc, ghInst) ;
  767.             capSetCallbackOnError(ghWndCap, fpErrorCallback) ;
  768. #endif
  769. #if ENABLE_STATUS_CALLBACK
  770.             fpStatusCallback = MakeProcInstance((FARPROC)StatusCallbackProc, ghInst) ;
  771.             capSetCallbackOnStatus(ghWndCap, fpStatusCallback) ;
  772. #endif
  773. #if ENABLE_VIDEOFRAME_CALLBACKS
  774.             fpFrameCallback = MakeProcInstance((FARPROC)FrameCallbackProc, ghInst) ;
  775.             capSetCallbackOnFrame(ghWndCap, fpFrameCallback) ;
  776. #endif
  777. #if ENABLE_VIDEOSTREAM_CALLBACKS
  778.             fpVideoCallback = MakeProcInstance((FARPROC)VideoCallbackProc, ghInst) ;
  779.             capSetCallbackOnVideoStream(ghWndCap, fpVideoCallback) ;
  780. #endif
  781.             // Try to connect one of the MSVIDEO drivers
  782.             for (wIndex = 0 ; wIndex < MAXVIDDRIVERS ; wIndex++) {
  783.                 if (capGetDriverDescription(wIndex,
  784.                            (LPSTR)achDeviceName, sizeof(achDeviceName),
  785.                            (LPSTR)achDeviceVersion, sizeof(achDeviceVersion))) {
  786.  
  787.                     // There is such a driver in the "system.ini" file.
  788.                     // Append driver name to "Options" list in menu
  789.                     wsprintf(achBuffer, "&%d %s", wIndex, (LPSTR)achDeviceName) ;
  790.                     AppendMenu(hMenu, MF_ENABLED, IDM_O_DRIVERS+wIndex, achBuffer) ;
  791.  
  792.                     if (wDriverCount++ == 0) { 
  793.                         // Only if no other driver is already connected
  794.                         if (wError = capDriverConnect(ghWndCap, wIndex)) {
  795.                             CheckMenuItem(GetMenu(hWnd), IDM_O_DRIVERS+wIndex, MF_BYCOMMAND | MF_CHECKED) ;
  796.                             gwDeviceIndex = wIndex ;
  797.                         }
  798.                     }
  799.                 } // end of if (capGetDriverDesc..())
  800.             }
  801.  
  802.             // Now refresh menu, position capture window, start driver etc
  803.             DrawMenuBar(hWnd) ;
  804.             CenterCaptureWindow(hWnd, ghWndCap) ;
  805.             StartNewVideoChannel(hWnd, ghWndCap, gwDeviceIndex) ;
  806.  
  807.             break ;
  808.         }
  809.  
  810.         case WM_MOVE:
  811.         case WM_SIZE:
  812.             CenterCaptureWindow(hWnd, ghWndCap) ;
  813.             break ;
  814.  
  815.         case WM_PALETTECHANGED: 
  816.         case WM_QUERYNEWPALETTE:
  817.             // Pass the buck to Capture window proc
  818.             SendMessage(ghWndCap, Message, wParam, lParam) ;
  819.             break ;
  820.  
  821.         case WM_INITMENU:
  822.         {
  823.             BOOL          fResult ;
  824.  
  825.             // Initially check if "Options.PastePalette" should be enabled
  826.             fResult = IsClipboardFormatAvailable(CF_PALETTE) ?
  827.                       MF_ENABLED : MF_GRAYED ;
  828.             EnableMenuItem((HMENU) wParam, IDM_E_PASTEPALETTE, fResult) ;
  829.  
  830.         // Check/Uncheck Preview and Overlay
  831.             capGetStatus(ghWndCap, &gCapStatus, sizeof(CAPSTATUS)) ;
  832.             CheckMenuItem((HMENU)wParam, IDM_O_PREVIEW, gCapStatus.fLiveWindow
  833.                         ? MF_CHECKED : MF_UNCHECKED);
  834.             CheckMenuItem((HMENU)wParam, IDM_O_OVERLAY,gCapStatus.fOverlayWindow
  835.                         ? MF_CHECKED : MF_UNCHECKED);
  836.         }
  837.  
  838.         case WM_PAINT:
  839.         {
  840.             HDC           hDC ;
  841.             PAINTSTRUCT   ps ;
  842.  
  843.             hDC = BeginPaint(hWnd, &ps) ;
  844.  
  845.             // Included in case the background is not a pure color
  846.             SetBkMode(hDC, TRANSPARENT) ;
  847.  
  848.             EndPaint(hWnd, &ps) ;
  849.             break ;
  850.         }
  851.  
  852.         case WM_CLOSE:
  853.             // Disable and free all the callbacks
  854. #if ENABLE_ERROR_CALLBACK
  855.             capSetCallbackOnError(ghWndCap, NULL) ;
  856.             FreeProcInstance(fpErrorCallback) ;
  857. #endif
  858. #if ENABLE_STATUS_CALLBACK
  859.             capSetCallbackOnStatus(ghWndCap, NULL) ;
  860.             FreeProcInstance(fpStatusCallback) ;
  861. #endif
  862. #if ENABLE_VIDEOFRAME_CALLBACKS
  863.             capSetCallbackOnFrame(ghWndCap, NULL) ;
  864.             FreeProcInstance(fpFrameCallback) ;
  865. #endif
  866. #if ENABLE_VIDEOSTREAM_CALLBACKS
  867.             capSetCallbackOnVideoStream(ghWndCap, NULL) ;
  868.             FreeProcInstance(fpVideoCallback) ;
  869. #endif
  870.             // Destroy child windows, modeless dialogs, then this window...
  871.             
  872.             DestroyWindow(ghWndCap) ;
  873.             DestroyWindow(hWnd) ;
  874.             break ;
  875.  
  876.         case WM_QUERYENDSESSION:        // Don't allow endsession if dialog
  877.             if (fHaveDialogUp) {        //   is up.
  878.                 MessageBox(NULL, "Close dialogs before exiting Windows.", 
  879.                                 gachAppName,
  880.                                 MB_OK | MB_ICONEXCLAMATION) ;
  881.                 BringWindowToTop (hWnd);
  882.                 return FALSE;
  883.             }
  884.             else
  885.                 return TRUE;
  886.  
  887.         case WM_DESTROY:
  888.             PostQuitMessage(0) ;
  889.             break ;
  890.  
  891.         default:
  892.             return DefWindowProc(hWnd, Message, wParam, lParam) ;
  893.     }
  894.  
  895.     return 0L;
  896. }   // End of MainWndProc
  897. 
  898.